package com.orifine.orm.model;

import java.lang.reflect.Field;

import com.orifine.orm.Information;
import com.orifine.orm.Type;
import com.orifine.orm.TypeManager;
import com.orifine.orm.annotation.Column;
import com.orifine.orm.annotation.Id;
import com.orifine.orm.annotation.Join;
import com.orifine.orm.annotation.Length;
import com.orifine.orm.annotation.NotNull;
import com.orifine.orm.annotation.Unique;
import com.orifine.utils.ClassUtils;
import com.orifine.web.Domain;
import com.orifine.web.Property;
import com.orifine.web.Validator;

public class ColumnModel{
	private String name;
	private TableModel table;
	private Field field;
	
	private LengthModel length;
	private NotNullModel notNull;
	private UniqueModel unique;
	private IdModel id;
	private JoinModel join;
	private Object defaultValue;
	
	private ColumnModel joinColumn;
	
	void init(Field field, TableModel table){
		this.field = field;
		this.table = table;
		
		String columnAnnotationName = field.getAnnotation(Column.class).value();
		if(columnAnnotationName.equals("")) {
			name = ClassUtils.convertClassNameToDatabaseName(field.getName());
		} else {
			name = columnAnnotationName;
		}
		
		if(length == null){
			Length lengthAnnotation = field.getAnnotation(Length.class);
			if(lengthAnnotation != null){
				length = new LengthModel(lengthAnnotation);
			} else {
				length = new LengthModel();
			}
		}
		
		if(notNull == null){
			NotNull notNullAnnotation = field.getAnnotation(NotNull.class);
			if(notNullAnnotation != null){
				notNull = new NotNullModel(notNullAnnotation);
			} else {
				notNull = new NotNullModel();
			}
		}
		
		if(unique == null){
			Unique uniqueAnnotation = field.getAnnotation(Unique.class);
			if(uniqueAnnotation != null){
				unique = new UniqueModel(uniqueAnnotation);
			} else {
				unique = new UniqueModel();
			}
		}
		
		if(id == null){
			Id idAnnotation = field.getAnnotation(Id.class);
			if(idAnnotation != null){
				id = new IdModel(idAnnotation);
			} else {
				id = new IdModel();
			}
		}
		
		
		
		
		if(join == null){
			Join joinAnnotation = field.getAnnotation(Join.class);
			if(joinAnnotation != null){
				join = new JoinModel(joinAnnotation);
			} else {
				join = new JoinModel();
			}
		}
		
		TableModel joinTable = table.getDatabase().getTable(field.getType());
		if(joinTable != null){
			joinColumn = joinTable.getColumn(join.getValue());
			if(joinColumn == null){
				throw new RuntimeException(field+"在"+joinTable.getTableClass()+"找不到"+join.getValue()+"字段");
			}
		} else {
			Type type = TypeManager.getType(field.getType());
			if(type == null){
				throw new RuntimeException(field.toString()+"的类型不能识别，请捡查是否属于Type类型或Table类型");
			}
		}
		
		
		
		
//		if(info == null){
//			try {
//				info = (InformationModel)table.getTableClass().getDeclaredField(INFORMATION + ClassUtils.getUpperName(field.getName())).get(null);
//			} catch (SecurityException e) {
//			} catch (NoSuchFieldException e) {
//			} catch (IllegalArgumentException e) {
//			} catch (IllegalAccessException e) {
//			} catch (ClassCastException e){
//			}
//		}
		
		if(info == null){
			Type type = getType();
			if(type.getDefaultInfo(this) != null){
				info = type.getDefaultInfo(this);
			} else {
				throw new RuntimeException(type.getClass()+"没有默认的信息源来策略");
			}
		}
		info.init(this);
		
//		{
//			ColumnValidate columnValidate = null;
//			try{
//			columnValidate = (ColumnValidate) table.getTableClass().getDeclaredField(VALIDATE + ClassUtils.getUpperName(field.getName())).get(null);
//			} catch (SecurityException e) {
//			} catch (NoSuchFieldException e) {
//			} catch (IllegalArgumentException e) {
//			} catch (IllegalAccessException e) {
//			} catch (ClassCastException e){
//			}
//		}
		
		if(actualName == null){
			actualName = new Property(new Domain("model", ClassUtils.getLowerName(this.table.getTableClass().getSimpleName()), ClassUtils.getLowerName(this.field.getName())));
		}
		
		if(validates != null){
			for(Validator validateModel : validates){
				if(validateModel.getDomain() == null){
					validateModel.setDomain(actualName);
				}
			}
		}
	}
	
	ColumnModel getFinalJoinColumn(){
		if(joinColumn == null){
			return this;
		} else {
			return joinColumn.getFinalJoinColumn();
		}
	}
	
	public ColumnModel setName(String name) {
		this.name = name;
		return this;
	}
	
	public String getName() {
		return name;
	}
	
	public ColumnModel setDefault(Object defaultValue){
		this.defaultValue = defaultValue;
		return this;
	}
	
	public Object getDefault(){
		return defaultValue;
	}
	
	public LengthModel getLength() {
		return length;
	}

	public ColumnModel setLength(LengthModel length) {
		this.length = length;
		return this;
	}

	public NotNullModel getNotNull() {
		return notNull;
	}

	public ColumnModel setNotNull(NotNullModel notNull) {
		this.notNull = notNull;
		return this;
	}

	public UniqueModel getUnique() {
		return unique;
	}

	public ColumnModel setUnique(UniqueModel unique) {
		this.unique = unique;
		return this;
	}

	public IdModel getId() {
		return id;
	}

	public ColumnModel setId(IdModel id) {
		this.id = id;
		return this;
	}
	
	public Field getField() {
		return field;
	}
	
	public ColumnModel setJoin(JoinModel join) {
		this.join = join;
		return this;
	}
	
	public ColumnModel getJoinColumn() {
		return joinColumn;
	}

	public JoinModel getJoin() {
		return join;
	}

	public TableModel getTable() {
		return table;
	}
	
	public Type getType(){
		Type type = TypeManager.getType(field.getType());
		if(type != null){
			return type;
		} else if(joinColumn != null){
			return joinColumn.getType();
		} else {
			throw new RuntimeException(field +"的类型不能识别，请检查下类型是否属于Type类型或Table类型");
		}
	}
	
	public String getScriptType() {
		return getType().getScriptType(this);
	}
	
	/* Information */
	protected Information info;
	
	public Information getInformation() {
		Information joinInfo = null;
		if(joinColumn != null){
			joinInfo = joinColumn.getInformation();
		}
		if(joinInfo != null){
			return joinInfo;
		} else {
			return info;
		}
	}

	public ColumnModel setInformation(Information information) {
		this.info = information;
		return this;
	}
	
	/* Validate */
	protected Validator[] validates;
	
	public Validator[] getValidates(){
		return validates;
	}
	
	public ColumnModel setValidate(Validator... validates){
		this.validates = validates; 
		return this;
	}
	
	/* domain */
	protected Property actualName;
	
	public Property getActualName(){
		return this.actualName;
	}
	
	public ColumnModel setActualName(Property actualName){
		this.actualName = actualName;
		return this;
	}
	
	protected Boolean isAutoIncrement;
	
	public Boolean isAutoIncrement() {
		return isAutoIncrement;
	}

	public void setAutoIncrement(Boolean isAutoIncrement) {
		this.isAutoIncrement = isAutoIncrement;
	}

	public static final String INFORMATION = "information";
	public static final String VALIDATE = "validate";
}